package com.dux.commons.network.packet;

/**
 * 网络通信数据包的超类
 * 
 * @author 杜祥
 * @create 2013-6-1
 */
public abstract class AbstractPacket
{
	/**
	 * 默认的数据包的string标识形式
	 * 
	 * @see java.util.Formatter
	 * @see String#format(String, Object[])
	 */
	public static final String	TYPE_PATTERN	= "[%s] 0x%02X %s";

	/**
	 * 包的类型
	 */
	private final PacketType	packetType;

	/**
	 * 操作码
	 */
	private int					opcode;

	/**
	 * 构造一个新的数据包，并指定类型和操作码
	 * 
	 * @param packetType
	 *            		数据包的类型
	 * @param opcode
	 *            		操作码
	 */
	protected AbstractPacket(PacketType packetType, int opcode)
	{
		this.packetType = packetType;
		this.opcode = opcode;
	}

	/**
	 * 构造一个新的数据包，并指定包的类型.<br>
	 * 使用此构造以后，必须使用setOpcode方法设置操作码。
	 * 
	 * @param packetType
	 * 					数据包的类型
	 */
	protected AbstractPacket(PacketType packetType)
	{
		this.packetType = packetType;
	}

	/**
	 * 设置此数据包的操作码.<br>
	 * 
	 * @param opcode
	 * 					操作码
	 */
	protected void setOpcode(int opcode)
	{
		this.opcode = opcode;
	}

	/**
	 * 返回数据包的操作码
	 * 
	 * @return packet id
	 */
	public final int getOpcode()
	{
		return opcode;
	}

	/**
	 * 数据包的类型
	 * 
	 * @return 返回数据包的类型
	 * 
	 * @see com.game.commons.network.packet.AbstractBasePacket.PacketType
	 */
	public final PacketType getPacketType()
	{
		return packetType;
	}

	/**
	 * 返回数据包的名称.
	 * <p/>
	 * 相当于源代码中给出的底层类的简称。
	 * 
	 * @return packet name
	 * 
	 * @see Class#getSimpleName()
	 */
	public String getPacketName()
	{
		return this.getClass().getSimpleName();
	}

	/**
	 * 数据包的枚举.
	 */
	public static enum PacketType
	{
		/** 服务端包 */
		SERVER("S"),

		/** 客户端包 */
		CLIENT("C");

		/**
		 * string形式的数据包类型。
		 */
		private final String	name;

		/**
		 * 构造方法.
		 * 
		 * @param name			数据包类型的string表示形式
		 */
		private PacketType(String name)
		{
			this.name = name;
		}

		/**
		 * 返回数据包的string形式.
		 * 
		 * @return 包的名称.
		 */
		public String getName()
		{
			return name;
		}
	}

	/**
	 * 根据数据包的类型，操作码和名称返回字符串表示.
	 * 
	 * @return 数据包的字符串标识形式
	 * @see #TYPE_PATTERN
	 * @see java.util.Formatter
	 * @see String#format(String, Object[])
	 */
	@Override
	public String toString()
	{
		return String.format(TYPE_PATTERN, getPacketType().getName(), getOpcode(), getPacketName());
	}
}
